package com.example.demo.utils;


import com.example.demo.beans.JwtSignatureStatus;
import com.example.demo.config.AppProperties;
import io.jsonwebtoken.*;
import io.jsonwebtoken.security.SignatureException;
import org.springframework.stereotype.Component;

import javax.crypto.spec.SecretKeySpec;
import java.security.Key;
import java.util.Base64;
import java.util.Date;

@Component
public class JwtUtils {

    private AppProperties appProperties;
    private Key accessTokenKey;
    private Long accessTokenExpire;

    public JwtUtils(AppProperties appProperties) {
        this.appProperties = appProperties;
        String accessToken = appProperties.getJwt().getAccessToken();   // 获取用户生成 Key 的字符串
        accessTokenExpire = appProperties.getJwt().getExpire();  // 获取过期日期
        accessTokenKey = new SecretKeySpec(Base64.getDecoder().decode(accessToken), "HmacSHA512");  // 将字符串转换为 Key 对象
    }

    public  String createAccessToken(String subject) {
        return createAccessToken(accessTokenKey, accessTokenExpire, subject);
    }

    public String createAccessToken(Key key, Long expire, String subject) {
        return Jwts.builder().setSubject(subject)  // 设置用户
                .setIssuedAt(new Date())  // 设置颁发日期
                .setExpiration(new Date(System.currentTimeMillis() + expire))  // 设置过期七日
                .signWith(key, SignatureAlgorithm.HS512)  // 生成jwt
                .compact(); // 转字符串
    }

    public JwtSignatureStatus validateAccessToken(String jwt) {
        return this.validateAccessToken(accessTokenKey, jwt);
    }

    // 验证jwt
    public JwtSignatureStatus validateAccessToken(Key accessTokenKey, String jwt) {
        JwtSignatureStatus jss = new JwtSignatureStatus(); // jwt验签状态
        // 解析jwt,
        try {
            Claims claims = Jwts.parserBuilder().setSigningKey(accessTokenKey).build().parseClaimsJws(jwt).getBody();
            jss.setStatus(JwtSignatureStatus.Status.correct); // jwt是正常状态
        }catch (ExpiredJwtException expiredJwtException) {  // jwt过期了
            jss.setStatus(JwtSignatureStatus.Status.expire);
        }catch (MalformedJwtException | SignatureException | UnsupportedJwtException exception) { // jwt被篡改
            jss.setStatus(JwtSignatureStatus.Status.tamper);  // 被篡改状态
        }
        return jss;
    }
}
